package xyz.canran.tool.panel;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
import xyz.canran.tool.action.ProjectAction;
import xyz.canran.tool.body.CreateProjectBody;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.filechooser.FileSystemView;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

public class ProjectConfigurationPanel extends JPanel {

    public ProjectConfigurationPanel() {


        this.setPreferredSize(new Dimension(500, 900));
        this.setLayout(new FlowLayout(FlowLayout.LEADING,20,20));
        this.setVisible(true);

        // 项目名
        Box projectNameBox = Box.createHorizontalBox();
        JLabel projectNameLabel = new JLabel("项目名：");
        projectNameLabel.setPreferredSize(new Dimension(100, 20));
        JTextField projectNameTextField = new JTextField();
        projectNameTextField.setText("DefaultProject");
        projectNameTextField.setPreferredSize(new Dimension(300, 20));
        projectNameBox.add(projectNameLabel);
        projectNameBox.add(projectNameTextField);
        this.add(projectNameBox);


        // 位置， 提示：位置为项目父级目录
        Box locationBox = Box.createHorizontalBox();
        JLabel locationLabel = new JLabel("位置：");
        locationLabel.setPreferredSize(new Dimension(100, 20));
        JTextField locationTextField = new JTextField();
        String rootDir = System.getProperty("user.home");
        locationTextField.setText(rootDir);
        locationTextField.setPreferredSize(new Dimension(200, 20));
        JButton locationChooseButton = getLocationChooseButton(locationTextField);
        locationChooseButton.setPreferredSize(new Dimension(100, 20));
        locationBox.add(locationLabel);
        locationBox.add(locationTextField);
        locationBox.add(locationChooseButton);
        this.add(locationBox);

        // 是否继承自Spring Boot starter parent
        Box extendSpringBootStarterParentBox = Box.createHorizontalBox();
        JLabel extendSpringBootStarterParentLabel = new JLabel("<html>是否继承自<br>spring-boot-starter-parent:</html>");
        extendSpringBootStarterParentLabel.setPreferredSize(new Dimension(100, 60));
        JRadioButton isExtendSpringBootStarterParentButton = new JRadioButton("是", false);
        JRadioButton notExtendSpringBootStarterParentButton = new JRadioButton("否", true);
        // 创建一个按钮小组
        ButtonGroup extendSpringBootStarterParentButtonGroup = new ButtonGroup();
        extendSpringBootStarterParentButtonGroup.add(isExtendSpringBootStarterParentButton);
        extendSpringBootStarterParentButtonGroup.add(notExtendSpringBootStarterParentButton);
        extendSpringBootStarterParentBox.add(extendSpringBootStarterParentLabel);
        extendSpringBootStarterParentBox.add(isExtendSpringBootStarterParentButton);
        extendSpringBootStarterParentBox.add(notExtendSpringBootStarterParentButton);
        this.add(extendSpringBootStarterParentBox);

        // JDK 版本
        Box jdkVersionBox = Box.createHorizontalBox();
        JLabel jdkVersionLabel = new JLabel("JDK：");
        jdkVersionLabel.setPreferredSize(new Dimension(100, 10));
        JComboBox<String> jdkVersionComboBox = new JComboBox<>();
        jdkVersionComboBox.setPreferredSize(new Dimension(300,20));
        jdkVersionComboBox.addItem("17");
        jdkVersionComboBox.addItem("21");
        jdkVersionComboBox.addItem("11");
        jdkVersionComboBox.addItem("8");
        jdkVersionBox.add(jdkVersionLabel);
        jdkVersionBox.add(jdkVersionComboBox);
        this.add(jdkVersionBox);


        // GroupId
        Box groupIdBox = Box.createHorizontalBox();
        JLabel groupIdLabel = new JLabel("GroupId：");
        groupIdLabel.setPreferredSize(new Dimension(100, 20));
        JTextField groupIdTextField = new JTextField();
        groupIdTextField.setPreferredSize(new Dimension(300, 20));
        groupIdBox.add(groupIdLabel);
        groupIdBox.add(groupIdTextField);
        this.add(groupIdBox);


        // ArtifactId
        Box artifactIdBox = Box.createHorizontalBox(); //创建横向Box容器
        JLabel artifactIdLabel = new JLabel("ArtifactId：");
        artifactIdLabel.setPreferredSize(new Dimension(100, 20));
        JTextField artifactIdTextField = new JTextField();
        artifactIdTextField.setPreferredSize(new Dimension(300, 20));
        artifactIdBox.add(artifactIdLabel);
        artifactIdBox.add(artifactIdTextField);
        this.add(artifactIdBox);


        // Version
        Box versionBox = Box.createHorizontalBox();
        JLabel versionLabel = new JLabel("Version：");
        versionLabel.setPreferredSize(new Dimension(100, 20));
        JTextField versionTextField = new JTextField();
        versionTextField.setPreferredSize(new Dimension(300, 20));
        versionBox.add(versionLabel);
        versionBox.add(versionTextField);
        this.add(versionBox);


        // 包名，默认GroupId(小写).ArtifactId(小写)
        Box packageNameBox = Box.createHorizontalBox();
        JLabel packageNameLabel = new JLabel("包名：");
        packageNameLabel.setPreferredSize(new Dimension(100, 20));
        JTextField packageNameTextField = new JTextField();
        packageNameTextField.setPreferredSize(new Dimension(300, 20));
        packageNameBox.add(packageNameLabel);
        packageNameBox.add(packageNameTextField);
        this.add(packageNameBox);


        // 是否单模块项目，不是的话，输入目录结构/模块名称
        Box multiModuleProjectBox = Box.createHorizontalBox();
        JLabel multiModuleProjectLabel = new JLabel("是否多模块项目：");
        multiModuleProjectLabel.setPreferredSize(new Dimension(100, 20));
        JRadioButton singleModuleButton = new JRadioButton("单模块项目", true);
        JRadioButton multiModuleButton = new JRadioButton("多模块项目", false);
        // 创建一个按钮小组
        ButtonGroup multiModuleProjectButtonGroup = new ButtonGroup();
        multiModuleProjectButtonGroup.add(singleModuleButton);
        multiModuleProjectButtonGroup.add(multiModuleButton);

        multiModuleProjectBox.add(multiModuleProjectLabel);
        multiModuleProjectBox.add(singleModuleButton);
        multiModuleProjectBox.add(multiModuleButton);
        this.add(multiModuleProjectBox);

        // 各个模块 jar(默认)/war/pom(有子模块)
        Box projectStructBox = Box.createHorizontalBox();
        projectStructBox.setPreferredSize(new Dimension(500, 300));
        Box projectStructVerticalBox = Box.createVerticalBox();
        Box projectStructPanelBox = Box.createVerticalBox();
        JLabel projectStructLabel = new JLabel("添加项目结构：", SwingConstants.LEFT);
        projectStructLabel.setPreferredSize(new Dimension(300, 20));
        String projectName = projectNameTextField.getText();
        DefaultMutableTreeNode projectRootNode = new DefaultMutableTreeNode(projectName);
        JTree projectStructTree = new JTree(projectRootNode);
        projectStructTree.setPreferredSize(new Dimension(300, 90));
        projectStructTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        JScrollPane projectStructTreePane = new JScrollPane(projectStructTree);
        projectStructTreePane.setPreferredSize(new Dimension(300, 95));
        projectStructPanelBox.add(projectStructLabel);
        projectStructPanelBox.add(projectStructTreePane);
        JButton addTreeNode = new JButton("添加节点");
        JButton editTreeNode = new JButton("编辑节点");
        JButton deleteTreeNode = new JButton("删除节点");
        JButton addChildTreeNode = new JButton("添加子节点");
        JButton deleteChildTreeNode = new JButton("删除子节点");
        Box projectStructButtonBox = Box.createHorizontalBox();
        projectStructButtonBox.setPreferredSize(new Dimension(500, 50));
        projectStructButtonBox.add(addTreeNode);
        projectStructButtonBox.add(editTreeNode);
        projectStructButtonBox.add(deleteTreeNode);
        projectStructButtonBox.add(addChildTreeNode);
        projectStructButtonBox.add(deleteChildTreeNode);
        projectStructVerticalBox.add(projectStructPanelBox);
        projectStructVerticalBox.add(projectStructButtonBox);
        projectStructBox.add(projectStructVerticalBox);
        projectStructBox.setVisible(true);
        this.add(projectStructBox);
        projectStructTreeNodeButtonFunction(projectStructTree, projectRootNode,
                addTreeNode,  editTreeNode, deleteTreeNode, addChildTreeNode, deleteChildTreeNode,
                singleModuleButton, multiModuleButton, projectNameTextField);


        // 创建和取消按钮
        Box functionBox = Box.createHorizontalBox();
        JButton createButton = new JButton("创建");
        JButton cancelButton = new JButton("取消");
        functionBox.add(createButton);
        functionBox.add(cancelButton);
        this.add(functionBox);

        // 添加事件监听
        groupIdTextField.addFocusListener(new FocusListener() {
            @Override
            public void focusGained(FocusEvent e) {

            }

            @Override
            public void focusLost(FocusEvent e) {
                String groupId = groupIdTextField.getText();
                String artifactId = artifactIdTextField.getText();
                if (!StrUtil.isBlankIfStr(groupId) && !StrUtil.isBlankIfStr(artifactId)) {
                    String packageName = groupId.toLowerCase(Locale.ROOT) + "." + artifactId.toLowerCase(Locale.ROOT);
                    packageNameTextField.setText(packageName);
                }
            }
        });

        artifactIdTextField.addFocusListener(new FocusListener() {
            @Override
            public void focusGained(FocusEvent e) {

            }

            @Override
            public void focusLost(FocusEvent e) {
                String groupId = groupIdTextField.getText();
                String artifactId = artifactIdTextField.getText();
                if (!StrUtil.isBlankIfStr(groupId) && !StrUtil.isBlankIfStr(artifactId)) {
                    String packageName = groupId.toLowerCase(Locale.ROOT) + "." + artifactId.toLowerCase(Locale.ROOT);
                    packageNameTextField.setText(packageName);
                }
            }
        });


        createButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String projectName = projectNameTextField.getText();
                String projectPath = locationTextField.getText();
                boolean isExtendSpringBootStarterParent = isExtendSpringBootStarterParentButton.isSelected();
                String jdkVersion = (String) jdkVersionComboBox.getSelectedItem();
                String groupId = groupIdTextField.getText();
                String artifactId = artifactIdTextField.getText();
                String version = versionTextField.getText();
                String packageName = packageNameTextField.getText();
                boolean isMultiModuleProject = multiModuleButton.isSelected();

                TreeModel model = projectStructTree.getModel();
                DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) model.getRoot();
                String rootNodeName = (String) rootNode.getUserObject();
                Map<String, Object> treeMap = new HashMap<>();
                treeMap.put(rootNodeName, new HashMap<>());
                buildChildrenMap(rootNode, treeMap);

                CreateProjectBody body =
                        new CreateProjectBody(projectName, projectPath, isExtendSpringBootStarterParent,
                                jdkVersion, groupId, artifactId, version, packageName, isMultiModuleProject, treeMap);

                System.out.println("body = " + JSONObject.toJSONString(body, JSONWriter.Feature.WriteMapNullValue));

                boolean result = ProjectAction.createProject(body);
                System.out.println("create result = " + result);
            }
        });

        cancelButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
    }

    // 递归函数
    private void buildChildrenMap(DefaultMutableTreeNode node, Map<String, Object> nodeMap) {

        Enumeration<TreeNode> children = node.children();
        String nodeName = (String) node.getUserObject();
        Map<String, Object> nodeChildrenNodeMap =
                (Map<String, Object>) nodeMap.getOrDefault(nodeName, new HashMap<>());
        while (children.hasMoreElements()) {
            DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
            String childName = (String) child.getUserObject();
            // 是否叶子节点
            if (child.isLeaf()) {
                nodeChildrenNodeMap.put(childName, null);
                nodeMap.put(nodeName, nodeChildrenNodeMap);
            } else {
                nodeChildrenNodeMap.put(childName, new HashMap<>());
                // 非叶子节点则继续递归调用了
                buildChildrenMap(child, nodeChildrenNodeMap);
                nodeMap.put(nodeName, nodeChildrenNodeMap);
            }
        }
    }

    private JButton getLocationChooseButton(JTextField locationTextField) {
        JButton locationChooseButton = new JButton("选择位置");

        locationChooseButton.addActionListener(e -> {
            JFileChooser locationChooser = new JFileChooser();
            // 得到桌面路径
            locationChooser.setCurrentDirectory(FileSystemView.getFileSystemView().getHomeDirectory());
            // 选择目录模式
            locationChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            //保存文件，指定路径
            int a = locationChooser.showSaveDialog(null);
            // 如果选中目录
            if(a == JFileChooser.APPROVE_OPTION){
                try {
                    File selectedFile = locationChooser.getSelectedFile();
                    String fileName = selectedFile.getCanonicalPath();
                    locationTextField.setText(fileName);
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }

            }
        });
        return locationChooseButton;
    }


    private static void projectStructTreeNodeButtonFunction(
            JTree projectStructTree, DefaultMutableTreeNode projectRootNode,
            JButton addTreeNode, JButton editTreeNode, JButton deleteTreeNode, JButton addChildTreeNode, JButton deleteChildTreeNode,
            JRadioButton singleModuleButton, JRadioButton multiModuleButton, JTextField projectNameTextField) {

        singleModuleButton.addFocusListener(new FocusListener() {
            @Override
            public void focusGained(FocusEvent e) {
                projectRootNode.setUserObject(projectNameTextField.getText());
                projectRootNode.removeAllChildren();
                projectRootNode.setAllowsChildren(false);
                projectStructTree.updateUI();
            }

            @Override
            public void focusLost(FocusEvent e) {

            }
        });

        multiModuleButton.addFocusListener(new FocusListener() {
            @Override
            public void focusGained(FocusEvent e) {
                projectRootNode.setUserObject(projectNameTextField.getText());
                projectRootNode.setAllowsChildren(true);
                projectStructTree.updateUI();
            }

            @Override
            public void focusLost(FocusEvent e) {

            }
        });

        projectNameTextField.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                projectRootNode.setUserObject(projectNameTextField.getText());
                projectStructTree.updateUI();
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                projectRootNode.setUserObject(projectNameTextField.getText());
                projectStructTree.updateUI();
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                projectRootNode.setUserObject(projectNameTextField.getText());
                projectStructTree.updateUI();
            }
        });

        // 添加节点功能
        addTreeNode.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                boolean selected = multiModuleButton.isSelected();
                if (!selected) {
                    return;
                }
                DefaultMutableTreeNode selectNode =
                        (DefaultMutableTreeNode) projectStructTree.getLastSelectedPathComponent();
                if (selectNode == null) {
                    return;
                }
                String newNodeName =
                        JOptionPane.showInputDialog(null, "请输入节点名称", "新节点名称", JOptionPane.WARNING_MESSAGE);
                if (StrUtil.isBlankIfStr(newNodeName)) {
                    return;
                }
                DefaultMutableTreeNode parentNode = null;
                if (selectNode == projectRootNode) {
                    parentNode = projectRootNode;
                } else {
                    parentNode = (DefaultMutableTreeNode) selectNode.getParent();
                }

                DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(newNodeName);
                parentNode.add(newNode);

                // 将新节点展示
                DefaultTreeModel model = (DefaultTreeModel) projectStructTree.getModel();
                TreeNode[] nodes = model.getPathToRoot(newNode);
                TreePath treePath = new TreePath(nodes);
                projectStructTree.scrollPathToVisible(treePath);
                //projectStructTree.setSelectionPath(treePath);
                projectStructTree.updateUI();

            }
        });

        // 编辑功能
        editTreeNode.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                boolean selected = multiModuleButton.isSelected();
                if (!selected) {
                    return;
                }
                DefaultMutableTreeNode selectNode =
                        (DefaultMutableTreeNode) projectStructTree.getLastSelectedPathComponent();
                if (selectNode == null) {
                    return;
                }
                String nodeOldName = (String) selectNode.getUserObject();
                String nodeNewName = (String)
                        JOptionPane.showInputDialog(null, "请输入节点新名称", "节点新名称",
                                JOptionPane.WARNING_MESSAGE, null, null, nodeOldName);
                if (StrUtil.isBlankIfStr(nodeNewName)) {
                    return;
                }
                selectNode.setUserObject(nodeNewName);
                projectStructTree.updateUI();
            }
        });

        // 删除节点功能
        deleteTreeNode.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                boolean selected = multiModuleButton.isSelected();
                if (!selected) {
                    return;
                }
                DefaultMutableTreeNode selectNode =
                        (DefaultMutableTreeNode) projectStructTree.getLastSelectedPathComponent();
                if (selectNode == null) {
                    return;
                }

                DefaultTreeModel model = (DefaultTreeModel) projectStructTree.getModel();
                model.removeNodeFromParent(selectNode);
            }
        });

        // 添加子节点功能
        addChildTreeNode.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                boolean selected = multiModuleButton.isSelected();
                if (!selected) {
                    return;
                }
                DefaultMutableTreeNode selectNode =
                        (DefaultMutableTreeNode) projectStructTree.getLastSelectedPathComponent();
                if (selectNode == null) {
                    return;
                }

                String newNodeName = JOptionPane.showInputDialog(null, "请输入子节点名称", "新子节点名称", JOptionPane.WARNING_MESSAGE);
                if (StrUtil.isBlankIfStr(newNodeName)) {
                    return;
                }
                DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(newNodeName);
                selectNode.add(newNode);

                // 将新节点展示
                DefaultTreeModel model = (DefaultTreeModel) projectStructTree.getModel();
                TreeNode[] nodes = model.getPathToRoot(newNode);
                TreePath treePath = new TreePath(nodes);
                projectStructTree.scrollPathToVisible(treePath);
                //projectStructTree.setSelectionPath(treePath);
                projectStructTree.updateUI();
            }
        });

        // 删除全部子节点
        deleteChildTreeNode.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                boolean selected = multiModuleButton.isSelected();
                if (!selected) {
                    return;
                }
                DefaultMutableTreeNode selectNode =
                        (DefaultMutableTreeNode) projectStructTree.getLastSelectedPathComponent();
                if (selectNode == null) {
                    return;
                }

                selectNode.removeAllChildren();
                projectStructTree.updateUI();
            }
        });
    }
}
